import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import { TaskType, User, UserDocument } from 'src/schemas/user.schema';
import { ChatPrivateItem } from './interface/chat.interface';

@Injectable()
export class ChatService {
  constructor(@InjectModel(User.name) private userModel: Model<UserDocument>) {}

  /**
   *
   * @returns {object}
   * code 0 ok
   * code 1 不在对方通讯录中
   * code 2 自己或对方不存在，（只要不乱改表，不会出现）
   */
  async sendPrivate(
    chatPrivateItem: ChatPrivateItem,
    myId: Types.ObjectId,
    goalId: Types.ObjectId,
  ) {
    // 获取两个人的信息
    const myselfItem = await this.userModel.findOne({
      _id: myId,
    });
    const anyoneItem = await this.userModel.findOne({
      _id: goalId,
    });
    // 检查是否存在
    if (anyoneItem && myselfItem) {
      // 检查是否在对方通讯录中
      const index = anyoneItem.address_book.findIndex((i) => {
        if (i.id.equals(myId)) {
          return true;
        }
      });
      if (index === -1) {
        return {
          code: 1,
        };
      }
      // 在对方通讯录中，就将消息添加到双方记录中
      // 两人的聊天记录中该条消息为同一id，目的是未来可能会有撤回功能。
      const recordsItemId = new Types.ObjectId();
      const anyoneRecordsItem = {
        ...chatPrivateItem,
        user_id: myId,
        id: recordsItemId,
        mine: false,
      };
      const myselfRecordsItem = {
        ...chatPrivateItem,
        user_id: myId,
        mine: true,
        id: recordsItemId,
      };
      if (!anyoneItem.chat_map) {
        anyoneItem.chat_map = {};
      }
      if (!myselfItem.chat_map) {
        myselfItem.chat_map = {};
      }
      if (!anyoneItem.chat_map[myId.toHexString()]) {
        anyoneItem.chat_map[myId.toHexString()] = {
          user_id: myId,
          records: [],
        };
      }
      if (!myselfItem.chat_map[goalId.toHexString()]) {
        myselfItem.chat_map[goalId.toHexString()] = {
          user_id: goalId,
          records: [],
        };
      }
      anyoneItem.chat_map[myId.toHexString()].records.push(anyoneRecordsItem);
      myselfItem.chat_map[goalId.toHexString()].records.push(myselfRecordsItem);
      const m1 = new this.userModel(anyoneItem);
      const m2 = new this.userModel(myselfItem);
      await m1.save();
      await m2.save();
      return {
        code: 0,
        anyoneRecordsItemId: anyoneRecordsItem.id,
        myselfRecordsItemId: myselfRecordsItem.id,
      };
      // 到此处，IO已经完成
    } else {
      return {
        code: 2,
      };
    }
  }

  /**
   * 只是发送好友请求，不代表已经加上了
   * @returns {object}
   * code 0 ok,
   * code 1 对方通讯录中有自己
   * code 2 对方任务栈中有自己的好友请求
   */
  async friendRequest(myId: Types.ObjectId, goalId: Types.ObjectId) {
    const userItem = await this.userModel.findOne({
      _id: goalId,
    });
    // 检查对方通讯录是否有自己
    const addressBookItem = userItem.address_book.find((i) =>
      i.id.equals(myId),
    );
    // 如果存在就直接返回，不在进行下面的操作
    if (addressBookItem) {
      return {
        code: 1,
      };
    }
    // 查询对方的任务栈中加好友的请求是否已经存在。（好友请求在被拒绝或同意前只能发一次）
    const taskItem = userItem.task_stack.find(
      (i) => i.id.equals(myId) && i.type === TaskType.ADD_FRIEND,
    );
    if (!taskItem) {
      userItem.task_stack.push({
        id: myId,
        type: TaskType.ADD_FRIEND,
      });
      const m = new this.userModel(userItem);
      await m.save();
      return {
        code: 0,
      };
    } else {
      code: 2;
    }
  }

  /**
   *
   * @returns {object}
   * code 0 ok,
   * code 1 同意了个寂寞，自己任务栈中没有
   */
  async dealWithAddFriendRequest(
    myId: Types.ObjectId,
    goalId: Types.ObjectId,
    agreed: boolean,
  ) {
    // 获取自己的信息
    const myselfItem = await this.userModel.findOne({
      _id: myId,
    });
    // 查看自己的任务栈是否有对方发送的请求
    const taskItemIndex = myselfItem.task_stack.findIndex(
      (i) => i.id.equals(goalId) && i.type === TaskType.ADD_FRIEND,
    );
    // 存在的话
    if (taskItemIndex !== -1) {
      // 先删掉
      myselfItem.task_stack.splice(taskItemIndex, 1);
      // 如果同意的话
      if (agreed) {
        // 查询对方的信息
        const anyoneItem = await this.userModel.findOne({
          _id: goalId,
        });
        // 将处理添加好友的任务添加到对方的任务栈中
        anyoneItem.task_stack.push({
          type: TaskType.DEAL_WITH_ADD_FRIEND,
          id: myId,
          agreed,
        });
        // 将双方的添加的对方的通讯录中
        myselfItem.address_book.push({
          id: goalId,
          nickname: anyoneItem.info.nickname,
        });
        anyoneItem.address_book.push({
          id: myId,
          nickname: myselfItem.info.nickname,
        });
        const anyoneModel = new this.userModel(anyoneItem);
        // 保存对方的数据
        await anyoneModel.save();
      }
      const myselfModel = new this.userModel(myselfItem);
      // 保存自己的数据
      await myselfModel.save();
      return {
        code: 0,
      };
    } else {
      return {
        code: 1,
      };
    }
  }
}
